#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/mm_types.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <asm/uaccess.h>


static void mtest_list_vma(void)
{
	struct mm_struct *mm = current->mm;
	struct vm_area_struct *vma;
		
	printk("mtest_vma_list.......\n");
		
	down_read(&mm->mmap_sem);
	for(vma = mm->mmap; vma; vma = vma->vm_next){
		printk("vma  0x%lx-0x%lx", vma->vm_start, vma->vm_end);
		if(vma->vm_flags & VM_WRITE)
			printk("	write");
		if(vma->vm_flags & VM_READ)
			printk("	read");
		if(vma->vm_flags & VM_EXEC)
			printk("	exec");
		printk("\n");
	}
	up_read(&mm->mmap_sem);
}

static ssize_t mtest_write(struct file *file, const char __user *buffer, size_t count, loff_t *data)
{
	char buf[128];
	
	printk("mtest_write...................\n");
	if(count > sizeof(buf))
		return -EINVAL;

	if(copy_from_user(buf, buffer, count))
		return -EINVAL;

	if(0 == memcmp(buf, "listvma", 7)){
		mtest_list_vma();
	}
	return count;
}

static struct file_operations proc_mtest_operations = {
	.write = mtest_write,
};

static struct proc_dir_entry *mtest_proc_entry;

static int __init mtest_init(void)
{
	mtest_proc_entry = create_proc_entry("mtest", 0777, NULL);
	if(mtest_proc_entry == NULL){
		printk("create proc entry error\n");
		return -1;
	}
	
	printk("mtest_init successful\n");
	mtest_proc_entry->proc_fops = &proc_mtest_operations;
	return 0;
}

static void __exit mtest_exit(void)
{
	printk("mtest exit..........\n");
	remove_proc_entry("mtest", NULL);
}

MODULE_LICENSE("GPL");
module_init(mtest_init);
module_exit(mtest_exit);

